package ar.edu.utn.xcontainer;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;

import ar.edu.utn.exceptions.ReflectionException;


public class Container  implements ConfigurableContainer{
	private String name;
	private List<ComposeComponentDescription> components;
	private Hashtable<String, ComposeComponentDescription> indexKeyComponentsTable;
	private Hashtable<Class<?>, ComposeComponentDescription> indexClassComponentTable;
	private String inyectorMode;
	private ComponentFactory componentFactory;

	
	
	/*public <T> Object getComponent(Class<T> componentType){
	}
	
	public List<Object> getComponents(){
	}
	*/
	public Container(){
		this.components=new ArrayList<ComposeComponentDescription>();
		this.indexKeyComponentsTable = new Hashtable<String,ComposeComponentDescription>();
		this.componentFactory=new ComponentFactory();
		this.indexKeyComponentsTable=new Hashtable<String, ComposeComponentDescription>();
		this.indexClassComponentTable=new Hashtable<Class<?>, ComposeComponentDescription>();
	
	}
	
	public void addComponent(String key, String nameClass) throws ReflectionException{
		//TODO como en otros metodos de otras clases, estaria tener un getClass generico
		ComposeComponentDescription component= this.componentFactory.create(key, nameClass);
		this.components.add(component);
		this.indexKeyComponentsTable.put(key, component);
		
		try{
			this.indexClassComponentTable.put(Class.forName(nameClass), component);
		}catch (ClassNotFoundException e){
			throw new ReflectionException("No se pudo obtener la clase: "+ nameClass, e.getCause());
		}
	}
	
	public void removeComponent(String key){
		ComposeComponentDescription co=this.indexKeyComponentsTable.get(key);
		this.components.remove(co);
		this.indexKeyComponentsTable.remove(key);
	} 

	public ComposeComponentDescription getComponent(String key){
		return this.indexKeyComponentsTable.get(key);
	}
	
	public ComposeComponentDescription getComponent(Class<?> clazz){
		return this.indexClassComponentTable.get(clazz);
	}
	
	public  Object getComponentInstance(Class<?> clazz) throws ReflectionException{
		//TODO reemplazar los catch
		return this.getComponent(clazz).getInstanceComponent();	
	}
	
	public static Object getAComponentInstance(Class<?> clazz){
		//TODO eliminar metodo si no va
		return null;
	}
	
	/* Estos 2 no quiero que me deuelven Object sino un tipo parametrizado....ACOMODARLO*/
	public Object getComponentInstance(String key) throws ReflectionException {
		return this.getComponent(key).getInstanceComponent();
	}
	/*public Object getComponentInstance(Class<?> clazz){
		
		
		
		
	}*/


//	public Object getComponentInstance(String key){
//		
//		}
//	public Object getComponentInstance(Class<?> clazz){
//		
//	}

	public void start(){
	}
	
	public void stop(){
	}

	@Override
	public void addSimpleDependency(String key, String nameofProperty,
			Object value) {
		this.getComponent(key).addSimpleDependency(nameofProperty, value);
	}

	@Override
	public void addRefDependency() {
		// TODO Auto-generated method stub
	}	
	public void addConstructorArgument(String key,String type, Object value){
		this.getComponent(key).addConstructorArgument(type, value);	
	}
}